Entrega 1¶
- 1.-Utiliza la metodología CRISP-DM con su correcta identación dentro del Notebook.
- 2.-Identifica un target para la tarea de "regresión". CUPO_L1
- 3.-Identifica un target para la tarea de "clasificación". SUBSEGMENTO
- 4.-Utiliza librerías Numpy, ScikitLearn, matplotlib y seaborn.
- 5.-Realiza limpieza y preparación de los datos de forma adecuada.
- 6.-Elabora documentación del proceso (información del caso y de los datos).
- 7.-Aplica tratamiento a los datos atípico y datos perdidos (imputación de los datos).
- 8.-Usa estadísticos de tendencia central y de dispersión para explorar los datos.
- 9.-Propone normalizaciones o estandarización según sea necesario.
- 10.-Justifica "en texto" dentro del notebook cada técnica utilizada en el proceso.
Caso Fundamentos de Machine Learning¶
CONTEXTO CASO
Caso Banco “Monopoly/Dormammu” El banco Monopoly lleva muchos años atendiendo a sus clientes en Chile y recientemente ha sido adquirido por un Banco con capitales extranjeros llamado “Dormammu”. Dormammu ha encargado a sus ingenieros hacer estudios sobre los clientes del banco Monopoly, para conocer su comportamiento y detectar patrones. Además, debe analizar cómo será su estrategia para abordar estos nuevos clientes dado el uso que ellos hacen de sus productos financieros. Los ingenieros del área informática del banco Monopoly han extraído una base de datos según una solicitud recibida por el nuevo dueño del banco y la han compartido con los ingenieros de Dormammu que están en la sede de New York. La base contiene una muestra de clientes con 12 meses de información almacenada en variables mensuales por cada cliente. Usted es parte del equipo de ingenieros del banco Dormammu, y con sus colegas debe analizar esta base, limpiarla, seleccionar las variables que sirvan para alguna interpretación y entregar la mayor información posible a los dueños de este banco para que puedan conocer a los clientes, preparar una estrategia y abordar a este nuevo mercado. La base de datos tiene variables asociadas a información del cliente y variables mensuales, es decir una por cada mes, el cliente no se repite y las variables asociadas se van agregando como una columna más. Con esto, la base de datos tiene 574 variables y 51.124 registros. La descripción de las variables se muestra a continuación:
| Variable | Transformación | Descripcion |
|---|---|---|
| CORRELATIVO | Ninguna | Identificador cliente |
| Region | Ninguna | Region de Residencia |
| Renta | Ninguna | Renta del cliente |
| Sexo | Ninguna | Sexo |
| Subsegmento | Ninguna | Subsegmento |
| Edad | Ninguna | Edad |
| Adicional | Ninguna | Indicador de Tenecia de TC adicionales |
| Antiguedad | Ninguna | Antigüedad del cliente (meses) |
| CambioPin | Ninguna | Indicador del cambio de clave secreta de la tarjeta |
| Consumo | Ninguna | Indicador de Credito de Consumo |
| Debito | Ninguna | Indicador de Tenecia de TD |
| Ctacte | Ninguna | Indicador de Cuenta Corriente |
| Cuentas | Ninguna | Numero de cuentas que tiene el cliente |
| Hipotecario | Ninguna | Indicador de Credito Hipotecario |
| Internauta | Ninguna | Indicador de cliente Internauta que usa la web Monopoly |
| Monoproducto | Ninguna | Indicador de si el cliente es solo poseedor de una TC |
| TC | Ninguna | Numero de TC que tiene el cliente |
| Dualidad | Ninguna | Indicador de Dualidad (Cliente es dual si tiene 2 o mas TC) |
| CUPO_L1 | Ninguna | Cupo de la tarjeta credito para compras nacionales |
| CUPO_MX | Ninguna | Cupo de la tarjeta credito para compras internacionales |
| CUPO_L2 | Ninguna | Cupo de la tarjeta credito para avances en cuotas |
| Col_T12 | promedio | Colocacion del cliente en TC en el mes X |
| ColL1TE_T12 | Revolving del cliente en TC en el mes X | |
| EeccInt_T12 | promedio | Monto internacional exigido en el estado de cuenta del cliente en el mes X |
| EeccNac_T12 | promedio | Monto nacional exigido en el estado de cuenta del cliente en el mes X |
| Fac_T12 | Promedio | Monto facturado por el cliente en TC en el mes X |
| FacAI_T12 | Promedio | Monto facturado en avances internacionales por el cliente en TC en el mes X |
| FacAN_T12 | Promedio | Monto facturado en avances nacionales por el cliente en TC en el mes X |
| FacCCOT_T12 | Promedio | Monto facturado en compras en cuotas con tasa por el cliente en TC en el mes X |
| FacCCPC_T12 | Promedio | Monto facturado en compras en cuotas precio contado por el cliente en TC en el mes X |
| FacCI_T12 | Promedio | Monto facturado en compras internacionales por el cliente en TC en el mes X |
| FacCN_T12 | Promedio | Monto facturado en compras nacionales por el cliente en TC en el mes X |
| FacCOL_T12 | Promedio | Monto facturado en avances en cuotas por el cliente en TC en el mes X |
| FacDebAtm_T12 | Promedio | Monto facturado en avances por el cliente en TD en el mes X |
| FacDebCom_T12 | Promedio | Monto facturado en compras por el cliente en TD en el mes X |
| FacPAT_T12 | Promedio | Monto facturado en PAT por el cliente en TC en el mes X |
| FlgAct_T12 | Suma meses activos | Indicador de actividad en el mes X en la TC |
| FlgActAI_T12 | Suma meses activos | Indicador de actividad en avances internacionales en el mes X en la TC |
| FlgActAN_T12 | Suma meses activos | Indicador de actividad en avances nacionales en el mes X en la TC |
| FlgActCCOT_T12 | Suma meses activos | Indicador de actividad en compras nacionales en cuotas con tasa en el mes X en la TC |
| FlgActCCPC_T12 | Suma meses activos | Indicador de actividad en compras nacionales en cuotas precio contado en el mes X en la TC |
| FlgActCI_T12 | Suma meses activos | Indicador de actividad en compras internacionales en el mes X en la TC |
| FlgActCN_T12 | Suma meses activos | Indicador de actividad en compras nacionales en el mes X en la TC |
| FlgActCOL_T12 | Suma meses activos | Indicador de actividad en avances en cuotas con tasa en el mes X en la TC |
| FlgActPAT_T12 | Suma meses activos | Indicador de actividad en PAT en el mes X en la TC |
| PagoInt_T12 | promedio | Monto de pagos de deuda internacional del cliente en el mes X |
| PagoNac_T12 | promedio | Monto de pagos de deuda nacional del cliente en el mes X |
| Txs_T12 | Suma | Numero de transacciones realizados por el cliente en TC en el mes X |
| TxsAI_T12 | Suma | Numero de transacciones en avances internacionales realizados por el cliente en TC en el mes X |
| TxsAN_T12 | Suma | Numero de transacciones en avances nacionales realizados por el cliente en TC en el mes X |
| TxsCCOT_T12 | Suma | Numero de transacciones en compras en cuotas con tasa realizados por el cliente en TC en el mes X |
| TxsCCPC_T12 | Suma | Numero de transacciones en compras en cuotas precio contado realizados por el cliente en TC en el mes X |
| TxsCI_T12 | Suma | Numero de transacciones en compras internacionales realizados por el cliente en TC en el mes X |
| TxsCN_T12 | Suma | Numero de transacciones en compras nacionales realizados por el cliente en TC en el mes X |
| TxsCOL_T12 | Suma | Numero de transacciones en avances en cuotas por el cliente en TC en el mes X |
| TxsDebAtm_T12 | Suma | Numero de transacciones en avances realizados por el cliente en TD en el mes X |
| TxsDebCom_T12 | Suma | Numero de transacciones en compras realizados por el cliente en TD en el mes X |
| TxsPAT_T12 | Suma | Numero de transacciones en PAT realizados por el cliente en TC en el mes X |
| UsoL1_T12 | Promedio | Monto de deuda en la linea de compras en la TC en el mes X |
| UsoL2_T12 | Promedio | Monto de deuda en la linea de avances en cuotas en la TC en el mes X |
| UsoLI_T12 | Promedio | Monto de deuda en la linea de compras internacionales en la TC en el mes X |
Fase 1: Business Understanding¶
Objetivo de negocio
El objetivo principal del negocio es entender cómo se comportan los clientes del banco Monopoly para crear estrategias de marketing más efectivas en este nuevo mercado. Para lograrlo, vamos a analizar la información de la base de datos, centrándonos en dos aspectos clave: el nivel de ingresos de los clientes y su tipo de comportamiento de consumo. En este caso las variables a utilizar son (variable "SUBSEGMENTO") (variable "CUPO_L1").
Estas dos variables nos permitirán agrupar a los clientes en diferentes categorías según sus ingresos y hábitos de consumo. Esto nos dará una visión más clara de quiénes son nuestros clientes y cómo se comportan.
Una vez que tengamos estos grupos identificados, podremos crear estrategias de marketing específicas para cada uno. Por ejemplo, podemos diseñar productos y servicios personalizados para atender las necesidades particulares de cada grupo o lanzar campañas de marketing dirigidas exclusivamente a ellos.
El objetivo final es mejorar la experiencia de nuestros clientes en el banco Monopol y observar un aumento en su satisfacción.Finalmente esperamos que esto contribuya a incrementar los ingresos y la rentabilidad del banco.
Fase 2: Data Understanding¶
Librerias¶
# Insertar cuantos bloques de código consideren necesarios
# Se recomienda obtener estadísticos descriptivos para apoyar hipótesis inferenciales.
# Reconocer la naturaleza de los datos y como tratarlos en etapas posteriores y dar ideas de como se podría transformar.
# Identificar MissingValues, outliers, medidas de posición, medidas de dispersión etc.
!pip install gdown
!pip install plotly
import pandas as pd
import numpy as np
import gdown
import matplotlib.pyplot as plt
import seaborn as sb
import plotly.express as px
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import MinMaxScaler
Requirement already satisfied: gdown in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (4.7.1) Requirement already satisfied: filelock in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from gdown) (3.12.3) Requirement already satisfied: requests[socks] in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from gdown) (2.31.0) Requirement already satisfied: six in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from gdown) (1.16.0) Requirement already satisfied: tqdm in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from gdown) (4.66.1) Requirement already satisfied: beautifulsoup4 in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from gdown) (4.12.2) Requirement already satisfied: soupsieve>1.2 in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from beautifulsoup4->gdown) (2.3.2.post1) Requirement already satisfied: typing-extensions>=4.7.1 in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from filelock->gdown) (4.7.1) Requirement already satisfied: charset-normalizer<4,>=2 in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from requests[socks]->gdown) (2.0.12) Requirement already satisfied: idna<4,>=2.5 in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from requests[socks]->gdown) (3.4) Requirement already satisfied: urllib3<3,>=1.21.1 in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from requests[socks]->gdown) (1.26.15) Requirement already satisfied: certifi>=2017.4.17 in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from requests[socks]->gdown) (2023.7.22) Requirement already satisfied: PySocks!=1.5.7,>=1.5.6 in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from requests[socks]->gdown) (1.7.1) Requirement already satisfied: plotly in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (5.16.1) Requirement already satisfied: tenacity>=6.2.0 in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from plotly) (8.2.3) Requirement already satisfied: packaging in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from plotly) (23.1)
!pip install fancyimpute
from fancyimpute import IterativeImputer
Requirement already satisfied: fancyimpute in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (0.7.0) Requirement already satisfied: knnimpute>=0.1.0 in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from fancyimpute) (0.1.0) Requirement already satisfied: scikit-learn>=0.24.2 in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from fancyimpute) (1.0.2) Requirement already satisfied: cvxpy in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from fancyimpute) (1.3.2) Requirement already satisfied: cvxopt in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from fancyimpute) (1.3.2) Requirement already satisfied: pytest in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from fancyimpute) (7.4.2) Requirement already satisfied: nose in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from fancyimpute) (1.3.7) Requirement already satisfied: six in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from knnimpute>=0.1.0->fancyimpute) (1.16.0) Requirement already satisfied: numpy>=1.10 in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from knnimpute>=0.1.0->fancyimpute) (1.21.6) Requirement already satisfied: scipy>=1.1.0 in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from scikit-learn>=0.24.2->fancyimpute) (1.8.0) Requirement already satisfied: joblib>=0.11 in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from scikit-learn>=0.24.2->fancyimpute) (1.3.0) Requirement already satisfied: threadpoolctl>=2.0.0 in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from scikit-learn>=0.24.2->fancyimpute) (3.2.0) Requirement already satisfied: osqp>=0.4.1 in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from cvxpy->fancyimpute) (0.6.3) Requirement already satisfied: ecos>=2 in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from cvxpy->fancyimpute) (2.0.12) Requirement already satisfied: scs>=1.1.6 in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from cvxpy->fancyimpute) (3.2.3) Requirement already satisfied: setuptools>65.5.1 in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from cvxpy->fancyimpute) (68.2.0) Requirement already satisfied: iniconfig in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from pytest->fancyimpute) (2.0.0) Requirement already satisfied: packaging in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from pytest->fancyimpute) (23.1) Requirement already satisfied: pluggy<2.0,>=0.12 in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from pytest->fancyimpute) (1.3.0) Requirement already satisfied: exceptiongroup>=1.0.0rc8 in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from pytest->fancyimpute) (1.1.2) Requirement already satisfied: tomli>=1.0.0 in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from pytest->fancyimpute) (2.0.1) Requirement already satisfied: qdldl in /opt/saturncloud/envs/saturn/lib/python3.9/site-packages (from osqp>=0.4.1->cvxpy->fancyimpute) (0.1.7.post0)
Carga de datos¶
#carga de la carpeta drive
#se demora 30 seg
url = 'https://drive.google.com/drive/folders/1KyhbT-bw83JpbtOSWI7aDn3gWHF_OTV_?usp=sharing'
gdown.download_folder(url, quiet=True, use_cookies=False)
['/home/jovyan/workspace/machine_learning/Base_clientes_Monopoly_descripcion.xlsx', '/home/jovyan/workspace/machine_learning/Base_clientes_Monopoly_sample.xlsx', '/home/jovyan/workspace/machine_learning/Base_clientes_Monopoly.xlsx', '/home/jovyan/workspace/machine_learning/descarga (1).png', '/home/jovyan/workspace/machine_learning/descarga (2).png', '/home/jovyan/workspace/machine_learning/ET221_1_MLY0100.pdf.pdf', '/home/jovyan/workspace/machine_learning/ET221_2_MLY0100.pdf.pdf', '/home/jovyan/workspace/machine_learning/ET221_3A_MLY0100.pdf.pdf', '/home/jovyan/workspace/machine_learning/ET221_4A_MLY0100.pdf.pdf', '/home/jovyan/workspace/machine_learning/ET221_5A_MLY0100.pdf.pdf', '/home/jovyan/workspace/machine_learning/monopoly_entrega1.ipynb', '/home/jovyan/workspace/machine_learning/monopoly_esqueleto.ipynb', '/home/jovyan/workspace/machine_learning/monopoly1.ipynb']
#data monopoly completa
''' data = pd.read_excel('/content/machine_learning/Base_clientes_Monopoly.xlsx', index_col=0) '''
" data = pd.read_excel('/content/machine_learning/Base_clientes_Monopoly.xlsx', index_col=0) "
#data monopoly recortada para pruebas
#se demora 1 min
data = pd.read_excel('machine_learning/Base_clientes_Monopoly_sample.xlsx', index_col=0)
Funciones¶
## funcion para dar muestra de detalles del dataset
def check(df):
l=[]
columns=df.columns
for col in columns:
dtypes=df[col].dtypes
nunique=df[col].nunique()
sum_null=df[col].isnull().sum()
percen_null=round(sum_null/len(df[col])*100, 4)
l.append([col,dtypes,nunique,sum_null,percen_null])
df_check=pd.DataFrame(l)
df_check.columns=['column','dtypes','nunique','sum_null','percen_null']
return df_check
#funcion para separar las columnas con datos de usaurio y los datos por mes
def mon_column(df):
columns1=[]
columns2=[]
for column in df.columns.values:
if column[-4:-1] in ("_T0","_T1"):
columns2.append(column)
else:
columns1.append(column)
df1=df[columns1]
df2=df[columns2]
return(df1,df2)
#funcion para obtener datos de usuario y los datos de enero para analisis
def datosUsuariEnero(df):
columns2=[]
for column in df.columns.values:
if ((column[-4:-1] not in ("_T0","_T1")) or (column[-4:] in ("_T01",))):
columns2.append(column)
df2=df[columns2]
return(df2)
def out_zscore(data):
outliers = []
zscore = []
threshold = 3
mean = np.mean(data)
std = np.std(data)
# Check if std is not zero before calculating z-scores
if std != 0:
for i in data:
z_score = (i - mean) / std
zscore.append(z_score)
if np.abs(z_score) > threshold:
outliers.append(i)
return len(outliers)
def out_zscore2(data):
global outliers, zscore
outliers = []
zscore = []
threshold = 3
mean = np.mean(data)
std = np.std(data)
for i in data:
z_score = (i - mean) / std
zscore.append(z_score)
if np.abs(z_score) > threshold:
outliers.append(i)
return outliers, zscore
def find_outliers_zscore(data, threshold=3):
outliers_count = []
for column in data.columns:
col_data = data[column]
num_outliers = out_zscore(col_data)
outliers_count.append((column, num_outliers))
outliers_df = pd.DataFrame(outliers_count, columns=['Column', 'Outliers'])
return outliers_df
def out_iqr(data):
outliers = []
iqr_values = []
# Calculate the IQR
q1 = np.percentile(data, 25)
q3 = np.percentile(data, 75)
iqr = q3 - q1
# Define the lower and upper bounds for outliers
lower_bound = q1 - 1.5 * iqr
upper_bound = q3 + 1.5 * iqr
# Check for outliers and store them
for i in data:
if i < lower_bound or i > upper_bound:
outliers.append(i)
return len(outliers)
def out_iqr_lh(df , column):
global lower,upper
q25, q75 = np.quantile(df[column], 0.25), np.quantile(df[column], 0.75)
# calculate the IQR
iqr = q75 - q25
# calculate the outlier cutoff
cut_off = iqr * 1.5
# calculate the lower and upper bound value
lower, upper = q25 - cut_off, q75 + cut_off
print('The IQR is',iqr)
print('The lower bound value is', lower)
print('The upper bound value is', upper)
# Calculate the number of records below and above lower and above bound value respectively
df1 = df[df[column] > upper]
df2 = df[df[column] < lower]
return print('Total number of outliers are', df1.shape[0]+ df2.shape[0])
EDA Exploratory Data Analysis¶
#Primeras lineas del DF
data.head()
| Subsegmento | Sexo | Region | Edad | Renta | Antiguedad | Internauta | Adicional | Dualidad | Monoproducto | ... | ColMx_T01 | PagoNac_T01 | PagoInt_T01 | EeccNac_T01 | EeccInt_T01 | UsoL1_T01 | UsoL2_T01 | UsoLI_T01 | IndRev_T01 | target | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Id | |||||||||||||||||||||
| 27778 | 210 | M | 9.0 | 28 | 436069.0 | 35 | 1 | 0 | 1 | 0 | ... | 0.0 | 14181 | 0.0 | 53539 | 0.0 | 53539.00 | 218399 | 0.0 | R | 0 |
| 37220 | 210 | H | 13.0 | 24 | 664366.0 | 20 | 1 | 0 | 0 | 0 | ... | 0.0 | 9000 | 0.0 | 246496 | 0.0 | 246496.00 | 115364 | 0.0 | R | 0 |
| 5289 | 210 | M | 12.0 | 28 | 485999.0 | 16 | 1 | 0 | 1 | 0 | ... | 0.0 | 20550 | 0.0 | 80823 | 0.0 | 79853.00 | 172986 | 0.0 | R | 0 |
| 24673 | 220 | H | NaN | 25 | NaN | 14 | 0 | 0 | 0 | 0 | ... | 0.0 | 0 | 0.0 | 15249 | 0.0 | 15249.00 | 6966 | 0.0 | R | 0 |
| 27929 | 220 | M | 4.0 | 27 | NaN | 14 | 0 | 0 | 0 | 0 | ... | 0.0 | 70000 | 0.0 | 93591 | 0.0 | 36311.63 | 17949 | 0.0 | R | 0 |
5 rows × 573 columns
dfnuevo= datosUsuariEnero(data)
dfnuevo
| Subsegmento | Sexo | Region | Edad | Renta | Antiguedad | Internauta | Adicional | Dualidad | Monoproducto | ... | ColMx_T01 | PagoNac_T01 | PagoInt_T01 | EeccNac_T01 | EeccInt_T01 | UsoL1_T01 | UsoL2_T01 | UsoLI_T01 | IndRev_T01 | target | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Id | |||||||||||||||||||||
| 27778 | 210 | M | 9.0 | 28 | 436069.0 | 35 | 1 | 0 | 1 | 0 | ... | 0.0 | 14181 | 0.0 | 53539 | 0.0 | 53539.00 | 218399 | 0.0 | R | 0 |
| 37220 | 210 | H | 13.0 | 24 | 664366.0 | 20 | 1 | 0 | 0 | 0 | ... | 0.0 | 9000 | 0.0 | 246496 | 0.0 | 246496.00 | 115364 | 0.0 | R | 0 |
| 5289 | 210 | M | 12.0 | 28 | 485999.0 | 16 | 1 | 0 | 1 | 0 | ... | 0.0 | 20550 | 0.0 | 80823 | 0.0 | 79853.00 | 172986 | 0.0 | R | 0 |
| 24673 | 220 | H | NaN | 25 | NaN | 14 | 0 | 0 | 0 | 0 | ... | 0.0 | 0 | 0.0 | 15249 | 0.0 | 15249.00 | 6966 | 0.0 | R | 0 |
| 27929 | 220 | M | 4.0 | 27 | NaN | 14 | 0 | 0 | 0 | 0 | ... | 0.0 | 70000 | 0.0 | 93591 | 0.0 | 36311.63 | 17949 | 0.0 | R | 0 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 38406 | 220 | H | 13.0 | 22 | 88214.0 | 9 | 1 | 0 | 0 | 0 | ... | 0.0 | 0 | 0.0 | 41496 | 0.0 | 0.00 | 30184 | 0.0 | T | 0 |
| 7159 | 160 | H | 13.0 | 42 | 506029.0 | 34 | 1 | 0 | 0 | 0 | ... | 0.0 | 8000 | 0.0 | 254387 | 0.0 | 254387.00 | 0 | 0.0 | R | 0 |
| 9427 | 170 | H | 13.0 | 39 | 1181631.0 | 86 | 1 | 0 | 0 | 0 | ... | 0.0 | 30000 | 0.0 | 27182 | 0.0 | 27182.00 | 0 | 0.0 | R | 0 |
| 42142 | 160 | H | 8.0 | 60 | 346232.0 | 31 | 0 | 0 | 1 | 0 | ... | 0.0 | 5000 | 0.0 | 212699 | 0.0 | 212699.00 | 47272 | 0.0 | R | 1 |
| 5740 | 170 | M | 13.0 | 44 | 646476.0 | 84 | 1 | 0 | 1 | 0 | ... | 0.0 | 0 | 0.0 | 72033 | 0.0 | 72033.00 | 39052 | 0.0 | T | 0 |
5112 rows × 67 columns
#Datos del DF
data.info()
<class 'pandas.core.frame.DataFrame'> Int64Index: 5112 entries, 27778 to 5740 Columns: 573 entries, Subsegmento to target dtypes: float64(505), int64(55), object(13) memory usage: 22.4+ MB
# Tamaño de Filas y Columnas del DF
data.shape
(5112, 573)
#separacion de los datos por usuario y datos registros por mes
data_cliente,data_mensual = mon_column(data)
print(data_cliente.shape)
print(data_mensual.shape)
(5112, 21) (5112, 552)
Analis de datos de Clientes
#Atravez de la funcion Check se realiza un resumen del tipo de dato por columna,
# la cantidad de datos unicos, la cantidad de nulos, y el % de nulos respecto
# al total
check(data_cliente)
| column | dtypes | nunique | sum_null | percen_null | |
|---|---|---|---|---|---|
| 0 | Subsegmento | int64 | 8 | 0 | 0.0000 |
| 1 | Sexo | object | 2 | 0 | 0.0000 |
| 2 | Region | float64 | 13 | 10 | 0.1956 |
| 3 | Edad | int64 | 72 | 0 | 0.0000 |
| 4 | Renta | float64 | 3561 | 1353 | 26.4671 |
| 5 | Antiguedad | int64 | 175 | 0 | 0.0000 |
| 6 | Internauta | int64 | 2 | 0 | 0.0000 |
| 7 | Adicional | int64 | 2 | 0 | 0.0000 |
| 8 | Dualidad | int64 | 2 | 0 | 0.0000 |
| 9 | Monoproducto | int64 | 2 | 0 | 0.0000 |
| 10 | Ctacte | int64 | 2 | 0 | 0.0000 |
| 11 | Consumo | int64 | 2 | 0 | 0.0000 |
| 12 | Hipotecario | int64 | 2 | 0 | 0.0000 |
| 13 | Debito | int64 | 2 | 0 | 0.0000 |
| 14 | CambioPin | float64 | 1 | 1921 | 37.5782 |
| 15 | Cuentas | int64 | 5 | 0 | 0.0000 |
| 16 | TC | int64 | 7 | 0 | 0.0000 |
| 17 | CUPO_L1 | int64 | 1490 | 0 | 0.0000 |
| 18 | CUPO_L2 | float64 | 715 | 0 | 0.0000 |
| 19 | CUPO_MX | int64 | 745 | 0 | 0.0000 |
| 20 | target | int64 | 2 | 0 | 0.0000 |
Se puede apreciar que en este tramo de datos existen tres columnas con datos nulos.
- Región: Los nulos representan menos del 1 % de los datos, por lo que se pueden eliminar sin afectar significativamente el tamaño de la muestra.
- Renta: Los nulos representan el 26 % de los datos, lo que es una proporción considerable. Para evitar que los datos faltantes afecten los resultados del análisis, se plantea imputarlos utilizando técnicas como MICE.
- CambioPin: En este caso, los valores nulos se pueden interpretar como que el cliente no realizó el cambio de pin. Por lo tanto, se plantea reemplazarlos por el valor "0".
#descripcion estadistica de los datos del cliente
data_cliente.describe()
| Subsegmento | Region | Edad | Renta | Antiguedad | Internauta | Adicional | Dualidad | Monoproducto | Ctacte | Consumo | Hipotecario | Debito | CambioPin | Cuentas | TC | CUPO_L1 | CUPO_L2 | CUPO_MX | target | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| count | 5112.000000 | 5102.000000 | 5112.000000 | 3.759000e+03 | 5112.000000 | 5112.000000 | 5112.000000 | 5112.000000 | 5112.000000 | 5112.000000 | 5112.000000 | 5112.000000 | 5112.000000 | 3191.0 | 5112.000000 | 5112.000000 | 5.112000e+03 | 5.112000e+03 | 5112.000000 | 5112.000000 |
| mean | 181.839397 | 10.823795 | 38.787559 | 6.589134e+05 | 39.120696 | 0.680164 | 0.260172 | 0.369523 | 0.068466 | 0.920970 | 0.001565 | 0.139476 | 0.874804 | 1.0 | 1.391432 | 1.721440 | 1.116222e+06 | 3.219817e+05 | 1376.821401 | 0.090571 |
| std | 28.483270 | 3.389346 | 13.438289 | 3.967115e+05 | 36.290536 | 0.466458 | 0.438771 | 0.482723 | 0.252569 | 0.269812 | 0.039532 | 0.346476 | 0.330973 | 0.0 | 0.538436 | 0.862639 | 1.045975e+06 | 7.642932e+05 | 1573.067873 | 0.287026 |
| min | 151.000000 | 1.000000 | 19.000000 | 1.000000e+00 | 6.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 1.0 | 1.000000 | 1.000000 | 5.000000e+04 | 0.000000e+00 | 0.000000 | 0.000000 |
| 25% | 160.000000 | 9.000000 | 28.000000 | 4.188580e+05 | 14.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 1.000000 | 0.000000 | 0.000000 | 1.000000 | 1.0 | 1.000000 | 1.000000 | 4.000000e+05 | 1.000000e+03 | 300.000000 | 0.000000 |
| 50% | 170.000000 | 13.000000 | 35.000000 | 5.636170e+05 | 26.000000 | 1.000000 | 0.000000 | 0.000000 | 0.000000 | 1.000000 | 0.000000 | 0.000000 | 1.000000 | 1.0 | 1.000000 | 2.000000 | 8.000000e+05 | 1.000000e+05 | 1000.000000 | 0.000000 |
| 75% | 210.000000 | 13.000000 | 46.000000 | 8.068225e+05 | 54.000000 | 1.000000 | 1.000000 | 1.000000 | 0.000000 | 1.000000 | 0.000000 | 0.000000 | 1.000000 | 1.0 | 2.000000 | 2.000000 | 1.530000e+06 | 2.200000e+05 | 1831.500000 | 0.000000 |
| max | 811.000000 | 13.000000 | 93.000000 | 5.790824e+06 | 312.000000 | 1.000000 | 1.000000 | 1.000000 | 1.000000 | 1.000000 | 1.000000 | 1.000000 | 1.000000 | 1.0 | 5.000000 | 7.000000 | 1.049400e+07 | 1.116800e+07 | 19600.000000 | 1.000000 |
#mapa de calor de correlaciones en datos de clientes
plt.figure(figsize = (15,8))
sb.heatmap(data_cliente.corr().round(3), cmap='coolwarm', annot=True)
plt.title="Mapa Calor"
plt.show()
#Grafico de relacion entre variables
df_subset = data_cliente.sample(frac=0.02)
print(len(df_subset), df_subset.columns)
print(df_subset.shape)
sb.pairplot(df_subset)
102 Index(['Subsegmento', 'Sexo', 'Region', 'Edad', 'Renta', 'Antiguedad',
'Internauta', 'Adicional', 'Dualidad', 'Monoproducto', 'Ctacte',
'Consumo', 'Hipotecario', 'Debito', 'CambioPin', 'Cuentas', 'TC',
'CUPO_L1', 'CUPO_L2', 'CUPO_MX', 'target'],
dtype='object')
(102, 21)
<seaborn.axisgrid.PairGrid at 0x7ff2dbf1af10>
Analis de datos de registros por mes de Clientes
#Atravez de la funcion Check se realiza un resumen del tipo de dato por columna,
# la cantidad de datos unicos, la cantidad de nulos, y el % de nulos respecto
# al total
data_mensual_check=check(data_mensual)
data_mensual_check
| column | dtypes | nunique | sum_null | percen_null | |
|---|---|---|---|---|---|
| 0 | FlgAct_T12 | float64 | 2 | 836 | 16.3537 |
| 1 | FlgActCN_T12 | float64 | 2 | 836 | 16.3537 |
| 2 | FlgActCI_T12 | float64 | 2 | 836 | 16.3537 |
| 3 | FlgActAN_T12 | float64 | 2 | 836 | 16.3537 |
| 4 | FlgActAI_T12 | float64 | 2 | 836 | 16.3537 |
| ... | ... | ... | ... | ... | ... |
| 547 | EeccInt_T01 | float64 | 305 | 0 | 0.0000 |
| 548 | UsoL1_T01 | float64 | 4435 | 0 | 0.0000 |
| 549 | UsoL2_T01 | int64 | 3314 | 0 | 0.0000 |
| 550 | UsoLI_T01 | float64 | 313 | 0 | 0.0000 |
| 551 | IndRev_T01 | object | 3 | 0 | 0.0000 |
552 rows × 5 columns
#cantidad de columnas que continene datos nulos
len(data_mensual_check[data_mensual_check["sum_null"]>0])
506
#cantidad de columnas que el % de nulos es mayor que el 10%
len(data_mensual_check[data_mensual_check["percen_null"]>10])
138
#analizando datos de colunas IndRev_TXX del tipo Object
data["IndRev_T01"].unique()
array(['R', 'P', 'T'], dtype=object)
Se determina que existen 506 de 552 columnas con valores nulos.
Ademas, 138 columnas de 552 el % de nulos es mayor que el 10%.
Como los valores registrados en este tramos de la infomacion corresponde a numericos se pueden aplicar MICE para su imputacion.
Tambien se debe considerar realizar un transformacion previa en las columnas "IndRev_TXX" antes de la operacion sugerida.
#Descripcion estadistica de los Registros mensuales de Enero
data_mensual.iloc[:,-46:].describe()
| FlgAct_T01 | FlgActCN_T01 | FlgActCI_T01 | FlgActAN_T01 | FlgActAI_T01 | FlgActPAT_T01 | FlgActCCPC_T01 | FlgActCCOT_T01 | FlgActCOL_T01 | Fac_T01 | ... | ColL2AC_T01 | ColL2CC_T01 | ColMx_T01 | PagoNac_T01 | PagoInt_T01 | EeccNac_T01 | EeccInt_T01 | UsoL1_T01 | UsoL2_T01 | UsoLI_T01 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| count | 5112.000000 | 5112.00000 | 5112.000000 | 5112.000000 | 5112.000000 | 5112.000000 | 5112.000000 | 5112.000000 | 5112.000000 | 5.112000e+03 | ... | 5.112000e+03 | 5.112000e+03 | 5.112000e+03 | 5.112000e+03 | 5.112000e+03 | 5.112000e+03 | 5112.000000 | 5.112000e+03 | 5.112000e+03 | 5112.000000 |
| mean | 0.664710 | 0.58529 | 0.040102 | 0.030908 | 0.001956 | 0.133803 | 0.286972 | 0.101526 | 0.001565 | 7.163727e+04 | ... | 6.247437e+04 | 4.107607e+04 | 5.530910e+03 | 7.264162e+04 | 1.208558e+03 | 1.913094e+05 | 7.596050 | 1.817260e+05 | 1.291747e+05 | 8.987338 |
| std | 0.472138 | 0.49272 | 0.196217 | 0.173085 | 0.044190 | 0.340474 | 0.452393 | 0.302053 | 0.039532 | 1.412821e+05 | ... | 4.203266e+05 | 9.948940e+04 | 5.674680e+04 | 1.379294e+05 | 2.532578e+04 | 2.845051e+05 | 122.800419 | 2.863325e+05 | 4.320962e+05 | 126.358721 |
| min | 0.000000 | 0.00000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | -1.199000e+05 | ... | 0.000000e+00 | 0.000000e+00 | 0.000000e+00 | 0.000000e+00 | 0.000000e+00 | -8.769960e+05 | -4885.000000 | -8.769960e+05 | -2.000000e+00 | -4652.500000 |
| 25% | 0.000000 | 0.00000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000e+00 | ... | 0.000000e+00 | 0.000000e+00 | 0.000000e+00 | 5.000000e+03 | 0.000000e+00 | 3.128575e+04 | 0.000000 | 1.664075e+04 | 0.000000e+00 | 0.000000 |
| 50% | 1.000000 | 1.00000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 2.779750e+04 | ... | 0.000000e+00 | 0.000000e+00 | 0.000000e+00 | 3.300000e+04 | 0.000000e+00 | 9.074350e+04 | 0.000000 | 7.974000e+04 | 2.851650e+04 | 0.000000 |
| 75% | 1.000000 | 1.00000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 1.000000 | 0.000000 | 0.000000 | 8.845400e+04 | ... | 0.000000e+00 | 4.008150e+04 | 0.000000e+00 | 8.891975e+04 | 0.000000e+00 | 2.364485e+05 | 0.000000 | 2.276278e+05 | 9.524400e+04 | 0.000000 |
| max | 1.000000 | 1.00000 | 1.000000 | 1.000000 | 1.000000 | 1.000000 | 1.000000 | 1.000000 | 1.000000 | 2.793659e+06 | ... | 1.013884e+07 | 1.472740e+06 | 1.762587e+06 | 3.066190e+06 | 1.225290e+06 | 3.202962e+06 | 3341.650000 | 3.511191e+06 | 1.000609e+07 | 3341.650000 |
8 rows × 45 columns
#mapa de calor de correlaciones en los Registros mensuales de Enero
plt.figure(figsize = (30,30))
sb.heatmap(data_mensual.iloc[:,-46:].corr().round(3), cmap='coolwarm', annot=True)
plt.title="Mapa Calor"
plt.show()
#Grafico de relacion entre variables
df_subset2 = data_mensual.iloc[:,-46:].sample(frac=0.02)
print(len(df_subset2), df_subset2.columns)
print(df_subset2.shape)
sb.pairplot(df_subset2)
102 Index(['FlgAct_T01', 'FlgActCN_T01', 'FlgActCI_T01', 'FlgActAN_T01',
'FlgActAI_T01', 'FlgActPAT_T01', 'FlgActCCPC_T01', 'FlgActCCOT_T01',
'FlgActCOL_T01', 'Fac_T01', 'Txs_T01', 'FacCN_T01', 'TxsCN_T01',
'FacCI_T01', 'TxsCI_T01', 'FacAN_T01', 'TxsAN_T01', 'FacAI_T01',
'TxsAI_T01', 'FacPAT_T01', 'TxsPAT_T01', 'FacCCPC_T01', 'TxsCCPC_T01',
'FacCCOT_T01', 'TxsCCOT_T01', 'FacCOL_T01', 'TxsCOL_T01',
'FacDebCom_T01', 'TxsDebCom_T01', 'FacDebAtm_T01', 'TxsDebAtm_T01',
'Col_T01', 'ColL1T0_T01', 'ColL1TE_T01', 'ColL2T0_T01', 'ColL2AC_T01',
'ColL2CC_T01', 'ColMx_T01', 'PagoNac_T01', 'PagoInt_T01', 'EeccNac_T01',
'EeccInt_T01', 'UsoL1_T01', 'UsoL2_T01', 'UsoLI_T01', 'IndRev_T01'],
dtype='object')
(102, 46)
<seaborn.axisgrid.PairGrid at 0x7ff2c679a7f0>
Fase 3: Data Preparation¶
Imputación¶
#se remplazan los nulos por "0" en la columna "CambioPin"
data_imputada_CP= data.copy()
data_imputada_CP["CambioPin"].fillna(0, inplace=True)
data_imputada_CP["CambioPin"]
Id
27778 1.0
37220 0.0
5289 1.0
24673 0.0
27929 1.0
...
38406 1.0
7159 0.0
9427 1.0
42142 1.0
5740 0.0
Name: CambioPin, Length: 5112, dtype: float64
# Se utiliza label Encoder para transformar a valores numeros las columnas categoricas.
# IMPORTANTE: se utiliza LabelEncoder para poder ser procesado con MICE, en un paso posterior se debe pasar a ONE HOT encoding
data_imputada_LE= data_imputada_CP.copy()
le = LabelEncoder()
columns=data_imputada_LE.select_dtypes(include='object').columns.values
for column in columns:
mascara=data_imputada_LE[column].isnull()
data_imputada_LE[column] = le.fit_transform(data_imputada_LE[column])
data_imputada_LE[column][mascara]=np.nan
/tmp/ipykernel_10213/1418396582.py:10: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy data_imputada_LE[column][mascara]=np.nan
#Se separa los datos del tipo float e Int para poder se procesador con MICE
#ya que no acepta String
data_imputada_MICE=data_imputada_LE.select_dtypes(include=["float64","int64"])
#Se crea una copia recortada del DF para que no sature la RAM de Colaborate
data_imputada_MICE=data_imputada_MICE.sample(frac=0.5)
#Se cuenta la cantidad total de nulos antes del MICE
data_imputada_MICE.isnull().sum().sum()
60374
#se extra el mayor y menor valor de cada columna dentro de la tabla para
#establecerlo como parametro en la funcion de MICE IterativeImputer
min = data_imputada_MICE.iloc[:,:].min(axis=0)
max = data_imputada_MICE.iloc[:,:].max(axis=0)
#en las tablas de valores de 0 y 1 si en la muestra se estra un valor unico,
#es decir, solo se extrajo 0, para que no produsca un error se define el max
# y el minimo de forma manual en 1 y 0 respectivamente
for i in range(len(min)):
if min[i]>=max[i]:
min[i]=0
max[i]=1
print(f"valor minimo {min}")
print("\n------------------\n")
print(f"valor maximo {max}")
valor minimo Subsegmento 151.00
Sexo 0.00
Region 1.00
Edad 19.00
Renta 1.00
...
UsoL1_T01 -876996.00
UsoL2_T01 -2.00
UsoLI_T01 -437.16
IndRev_T01 0.00
target 0.00
Length: 573, dtype: float64
------------------
valor maximo Subsegmento 811.00
Sexo 1.00
Region 13.00
Edad 93.00
Renta 5790824.00
...
UsoL1_T01 3511191.00
UsoL2_T01 8315098.00
UsoLI_T01 2439.21
IndRev_T01 2.00
target 1.00
Length: 573, dtype: float64
# Crear una instancia de IterativeImputer
#parametros:
#max_iter= 3 maxima cantidad de itineraciones igual a 3
#min_value= min se le entrega el minimo ya existente en la DB
#min_value= min se le entrega el maximo ya existente en la DB
#se entregan los valores min y max para que los resultados no se desboden
# y genere un error
imputer=IterativeImputer( max_iter= 3, min_value=min, max_value=max)
imputed_np = imputer.fit_transform(data_imputada_MICE)
columns_names_df = data_imputada_MICE.columns.values
data_imputada_ok = pd.DataFrame(imputed_np, columns = columns_names_df)
data_imputada_ok
/opt/saturncloud/envs/saturn/lib/python3.9/site-packages/sklearn/impute/_iterative.py:699: ConvergenceWarning: [IterativeImputer] Early stopping criterion not reached. warnings.warn(
| Subsegmento | Sexo | Region | Edad | Renta | Antiguedad | Internauta | Adicional | Dualidad | Monoproducto | ... | ColMx_T01 | PagoNac_T01 | PagoInt_T01 | EeccNac_T01 | EeccInt_T01 | UsoL1_T01 | UsoL2_T01 | UsoLI_T01 | IndRev_T01 | target | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 220.0 | 1.0 | 13.0 | 24.0 | 4.921897e+05 | 12.0 | 1.0 | 1.0 | 0.0 | 0.0 | ... | 0.0 | 5000.0 | 0.00 | 61162.0 | 0.00 | 41162.0 | 0.0 | 0.00 | 1.0 | 0.0 |
| 1 | 151.0 | 0.0 | 2.0 | 62.0 | 9.227165e+05 | 153.0 | 0.0 | 0.0 | 0.0 | 1.0 | ... | 0.0 | 36000.0 | 0.00 | 1210977.0 | 0.00 | 1231027.0 | 308965.0 | 0.00 | 1.0 | 0.0 |
| 2 | 160.0 | 1.0 | 13.0 | 45.0 | 2.665800e+05 | 120.0 | 1.0 | 1.0 | 1.0 | 0.0 | ... | 0.0 | 8145.0 | 30065.22 | 17101.0 | -0.72 | 22601.0 | 46186.0 | -0.72 | 2.0 | 0.0 |
| 3 | 160.0 | 0.0 | 13.0 | 51.0 | 5.817030e+05 | 24.0 | 1.0 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 16000.0 | 0.00 | 270298.0 | 0.00 | 276298.0 | 80885.0 | 0.00 | 1.0 | 0.0 |
| 4 | 220.0 | 1.0 | 7.0 | 27.0 | 4.522378e+05 | 19.0 | 0.0 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 10000.0 | 0.00 | 75236.0 | 0.00 | 75236.0 | 62599.0 | 0.00 | 1.0 | 0.0 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 2551 | 170.0 | 1.0 | 7.0 | 41.0 | 8.565990e+05 | 11.0 | 0.0 | 0.0 | 1.0 | 0.0 | ... | 0.0 | 20000.0 | 0.00 | 17728.0 | 0.00 | -2272.0 | 94637.0 | 0.00 | 1.0 | 1.0 |
| 2552 | 160.0 | 1.0 | 6.0 | 60.0 | 9.892800e+04 | 8.0 | 0.0 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 42182.0 | 0.00 | 42186.0 | 0.00 | 42186.0 | 0.0 | 0.00 | 0.0 | 0.0 |
| 2553 | 220.0 | 1.0 | 2.0 | 29.0 | 4.395210e+05 | 27.0 | 0.0 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.0 | 0.00 | 19732.0 | 0.00 | 19732.0 | 19266.0 | 0.00 | 0.0 | 0.0 |
| 2554 | 160.0 | 0.0 | 13.0 | 34.0 | 5.915130e+05 | 7.0 | 0.0 | 0.0 | 1.0 | 0.0 | ... | 0.0 | 0.0 | 0.00 | 482387.0 | 0.00 | 482387.0 | 79839.0 | 0.00 | 1.0 | 0.0 |
| 2555 | 170.0 | 0.0 | 13.0 | 35.0 | 1.135570e+06 | 36.0 | 1.0 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 154127.0 | 0.00 | 148701.0 | 0.00 | 148701.0 | 0.0 | 0.00 | 1.0 | 0.0 |
2556 rows × 573 columns
#se comprueba la cantidad final de nulos luego de MICE
data_imputada_ok.isnull().sum().sum()
0
Outliers¶
Para analizar los outliers, se tomó la decisión de utilizar dos métodos ampliamente aceptados, el Z-Score y el IQR (Rango Intercuartílico). Estos métodos proporcionarán resultados diversos y más apropiados según las características de los datos en cada columna, permitiendo una evaluación más completa de los valores atípicos y su significado en el contexto de los datos.
Utilizar tanto el método del IQR como el Z-Score para el análisis de outliers es beneficioso porque:
El IQR es robusto y eficaz para identificar valores extremos en distribuciones no normales o sesgadas. El Z-Score estandariza los datos y proporciona una medida cuantitativa de rareza. Combinar ambos métodos proporciona mayor confiabilidad al identificar valores atípicos y se adapta a diferentes distribuciones de datos.
#Se crea un filtro de tablas que contengan más de 3 valores unicos
#dejando fuera columnas de [0,1] y de clasificacion como IndRev_TXX
df_filtro=check(data)
filtro=df_filtro[df_filtro["nunique"]>3]["column"]
filtro
0 Subsegmento
2 Region
3 Edad
4 Renta
5 Antiguedad
...
566 EeccNac_T01
567 EeccInt_T01
568 UsoL1_T01
569 UsoL2_T01
570 UsoLI_T01
Name: column, Length: 430, dtype: object
#Se copia la tabla de datos imputados para comenzar a analizar outliers
elimOutliers = data_imputada_ok.copy()
Zscore¶
#Se aplica la funcion declarada mas arriba para detectar outliers utilizando zscore
outliers_zscore = find_outliers_zscore(elimOutliers[filtro])
# se gráfican las 12 columnas con mas Outliers encontrados
melted_df = pd.melt(
outliers_zscore, id_vars="Column", value_vars="Outliers", var_name="Metric"
)
filtered_melted_df=melted_df.sort_values("value",ascending=False).head(12)
# Gráfico de barras
plt.figure(figsize=(20, 5))
fig=sb.barplot(x = filtered_melted_df["Column"], y = filtered_melted_df["value"],color = "blue")
plt.xlabel("Nombre columna")
plt.ylabel("Numero de outliers")
plt.bar_label(fig.containers[0])
plt.legend()
plt.show()
No artists with labels found to put in legend. Note that artists whose label start with an underscore are ignored when legend() is called with no argument.
filtered_melted_df.sort_values("value",ascending=False)
| Column | Metric | value | |
|---|---|---|---|
| 86 | FacAN_T10 | Outliers | 250 |
| 96 | FacCOL_T10 | Outliers | 250 |
| 104 | ColL2T0_T10 | Outliers | 249 |
| 149 | UsoLI_T09 | Outliers | 191 |
| 131 | FacCOL_T09 | Outliers | 190 |
| 143 | PagoNac_T09 | Outliers | 190 |
| 148 | UsoL2_T09 | Outliers | 190 |
| 126 | TxsPAT_T09 | Outliers | 189 |
| 136 | Col_T09 | Outliers | 189 |
| 140 | ColL2AC_T09 | Outliers | 189 |
| 142 | ColMx_T09 | Outliers | 189 |
| 139 | ColL2T0_T09 | Outliers | 188 |
Para mostrar en mayor detalle los datos observados en el grafico, se tomaron las columnas mas extremas y se les aplico un histograma, a la vez marcando una posible seccion de outlier.
outliers, zscore = out_zscore2(elimOutliers.FacCN_T10)
# Crea histograma de zscore
plt.figure(figsize=(10, 5))
sb.histplot(zscore, bins=20, kde=True, color='blue')
plt.xlabel('Z-Score')
plt.ylabel('Frequency')
shaded_upper_limit = 10 # Ajusta tope superior
# Agrega seccion demarcada de outliers
if len(outliers) > 0:
plt.axvspan(xmin=2, xmax=shaded_upper_limit, alpha=0.2, color='red')
plt.legend()
plt.show()
No artists with labels found to put in legend. Note that artists whose label start with an underscore are ignored when legend() is called with no argument.
Finalmente se grafico en boxplot la columna con mayor cantidad de outliers
sb.boxplot(x = elimOutliers['FacCN_T10'])
<AxesSubplot:xlabel='FacCN_T10'>
IQR¶
Para el analisis utilizando IQR se realizo el mismo procedimiento de graficar outliers, analizar los extremos y graficar en boxplot el mas alto
iqr_results = [(column, out_iqr(elimOutliers[column])) for column in elimOutliers[filtro].columns]
iqr_df = pd.DataFrame(iqr_results, columns=['Column Name', 'IQR Outliers'])
filtered_iqr_df = iqr_df.sort_values("IQR Outliers",ascending=False).head(12)
# Gráfico de barras
plt.figure(figsize=(20, 5))
fig=sb.barplot(x = filtered_iqr_df["Column Name"], y = filtered_iqr_df["IQR Outliers"],color = "blue")
plt.xlabel("Nombre columna")
plt.ylabel("Numero de outliers")
plt.bar_label(fig.containers[0])
plt.legend()
plt.show()
No artists with labels found to put in legend. Note that artists whose label start with an underscore are ignored when legend() is called with no argument.
#listados de columnas con mas Outliers encontrados en el metodo IQR
filtered_iqr_df.sort_values("IQR Outliers",ascending=False)
| Column Name | IQR Outliers | |
|---|---|---|
| 55 | FacPAT_T11 | 634 |
| 58 | TxsCCPC_T11 | 627 |
| 25 | TxsCCOT_T12 | 617 |
| 24 | FacCCOT_T12 | 616 |
| 92 | FacCCPC_T10 | 614 |
| 91 | TxsPAT_T10 | 575 |
| 23 | TxsCCPC_T12 | 574 |
| 36 | ColL2CC_T12 | 559 |
| 57 | FacCCPC_T11 | 544 |
| 44 | UsoLI_T12 | 538 |
| 59 | FacCCOT_T11 | 533 |
| 41 | EeccInt_T12 | 532 |
# Crea histograma de zscore
outliers, zscore = out_zscore2(elimOutliers.FacCCOT_T12)
# Create a histogram of the z-scores
plt.figure(figsize=(10, 5))
sb.histplot(zscore, bins=20, kde=True, color='blue')
plt.xlabel('Z-Score')
plt.ylabel('Frequency')
shaded_upper_limit = 10 # Ajusta tope superior
# Agrega seccion demarcada de outliers
if len(outliers) > 0:
plt.axvspan(xmin=2, xmax=shaded_upper_limit, alpha=0.2, color='red')
plt.legend()
plt.show()
No artists with labels found to put in legend. Note that artists whose label start with an underscore are ignored when legend() is called with no argument.
sb.boxplot(x = elimOutliers['FacCCOT_T12'])
<AxesSubplot:xlabel='FacCCOT_T12'>
elimOutliers['FacCCOT_T12'].min()
0.0
elimOutliers['FacCCOT_T12'].max()
9035980.0
Conclusiones Outliers¶
En el análisis de los datos con las tecnicas de Zscore y IQR se detectaron valores atípicos, es decir, valores que se alejan de la tendencia central de sus respectivas columnas. Estos valores, si bien son inusuales, no son imposibles. Por ejemplo, en la columna "FacCCOT_T12" (Promedio de monto facturado en compras en cuotas con tasa por el cliente en TC en el mes X), existe un registro único mayor que 500.000. Si bien es inusual que un cliente realice una compra de esa cantidad, esta dentro de los límites que se pueden facturar.
Por lo tanto, se decidió mantener estos valores para su estudio.
Normalización¶
Una vez procesados los datos, y al tener todos los valores numéricos, se decidió aplicar el método de escalado Min-Max para transformar los datos a un rango de 0 a 1.
#Se aplica MInMAxScaler para poder normalizar los datos de la tabla
data_normalizada=data_imputada_ok.copy()
nombre_columnas= data_imputada_MICE.columns.values
mmscaler = MinMaxScaler()
np_normalizado=mmscaler.fit_transform(data_normalizada)
data_normalizada = pd.DataFrame(np_normalizado,columns=nombre_columnas)
data_normalizada
| Subsegmento | Sexo | Region | Edad | Renta | Antiguedad | Internauta | Adicional | Dualidad | Monoproducto | ... | ColMx_T01 | PagoNac_T01 | PagoInt_T01 | EeccNac_T01 | EeccInt_T01 | UsoL1_T01 | UsoL2_T01 | UsoLI_T01 | IndRev_T01 | target | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0.104545 | 1.0 | 1.000000 | 0.067568 | 0.084995 | 0.019608 | 1.0 | 1.0 | 0.0 | 0.0 | ... | 0.0 | 0.001631 | 0.000000 | 0.231776 | 0.151983 | 0.209234 | 2.405263e-07 | 0.151983 | 0.5 | 0.0 |
| 1 | 0.000000 | 0.0 | 0.083333 | 0.581081 | 0.159341 | 0.480392 | 0.0 | 0.0 | 0.0 | 1.0 | ... | 0.0 | 0.011741 | 0.000000 | 0.515842 | 0.151983 | 0.480386 | 3.715734e-02 | 0.151983 | 0.5 | 0.0 |
| 2 | 0.013636 | 1.0 | 1.000000 | 0.351351 | 0.046035 | 0.372549 | 1.0 | 1.0 | 1.0 | 0.0 | ... | 0.0 | 0.002656 | 0.024537 | 0.220890 | 0.151733 | 0.205004 | 5.554714e-03 | 0.151733 | 1.0 | 0.0 |
| 3 | 0.013636 | 0.0 | 1.000000 | 0.432432 | 0.100452 | 0.058824 | 1.0 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.005218 | 0.000000 | 0.283444 | 0.151983 | 0.262818 | 9.727724e-03 | 0.151983 | 0.5 | 0.0 |
| 4 | 0.104545 | 1.0 | 0.500000 | 0.108108 | 0.078095 | 0.042484 | 0.0 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.003261 | 0.000000 | 0.235253 | 0.151983 | 0.216999 | 7.528593e-03 | 0.151983 | 0.5 | 0.0 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 2551 | 0.028788 | 1.0 | 0.500000 | 0.297297 | 0.147923 | 0.016340 | 0.0 | 0.0 | 1.0 | 0.0 | ... | 0.0 | 0.006523 | 0.000000 | 0.221045 | 0.151983 | 0.199336 | 1.138158e-02 | 0.151983 | 0.5 | 1.0 |
| 2552 | 0.013636 | 1.0 | 0.416667 | 0.554054 | 0.017083 | 0.006536 | 0.0 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.013757 | 0.000000 | 0.227088 | 0.151983 | 0.209467 | 2.405263e-07 | 0.151983 | 0.0 | 0.0 |
| 2553 | 0.104545 | 1.0 | 0.083333 | 0.135135 | 0.075899 | 0.068627 | 0.0 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.000000 | 0.000000 | 0.221540 | 0.151983 | 0.204350 | 2.317230e-03 | 0.151983 | 0.0 | 0.0 |
| 2554 | 0.013636 | 0.0 | 1.000000 | 0.202703 | 0.102146 | 0.003268 | 0.0 | 0.0 | 1.0 | 0.0 | ... | 0.0 | 0.000000 | 0.000000 | 0.335841 | 0.151983 | 0.309782 | 9.601929e-03 | 0.151983 | 0.5 | 0.0 |
| 2555 | 0.028788 | 0.0 | 1.000000 | 0.216216 | 0.196098 | 0.098039 | 1.0 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.050267 | 0.000000 | 0.253403 | 0.151983 | 0.233740 | 2.405263e-07 | 0.151983 | 0.5 | 0.0 |
2556 rows × 573 columns
Fase 4: Modeling¶
Regresión¶
# Insertar cuantos bloques de código consideren necesarios
# Realizar tarea de regresión de datos orientado al caso entregado
Clasificación¶
# Insertar cuantos bloques de código consideren necesarios
# Realizar tarea de clasificación de datos orientado al caso entregado
Fase 5: Evaluation¶
# Insertar cuantos bloques de código consideren necesarios
# Evaluar con las métricas que corresponda los mejores modelos, explicar cual es mejor para cada tarea y por qué
Fase 6: Deployment¶
# Insertar cuantos bloques de código consideren necesarios
# Realizar despliegue del modelo